<template>
    <div class="backgournd-grid-app">
        <div class="app-content" id="container" ref="graphContainer"></div>
    </div>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { Graph, Node, Path, Edge, Platform } from '@antv/x6'
import { Selection } from '@antv/x6-plugin-selection'
import { register } from '@antv/x6-vue-shape';
import ProgressNode from '../../components/flow/ProgressNode.vue';
const props = defineProps({
    flowData: {
        type: String,
        default: '',
    }
})
console.log("flowData", props.flowData);
const graphContainer = ref<HTMLElement>();
const graph = ref<Graph | null>(null);
// 元素校验状态
enum CellStatus {
    DEFAULT = 'default',
    SUCCESS = 'success',
    ERROR = 'error',
}

register({
    shape: 'data-processing-dag-node',
    width: 212,
    height: 48,
    component: ProgressNode,
    data: {
        node: Node
    }, // 这里可以传递一些数据给节点组件，例如节点的名称、类型等
    // port默认不可见
    ports: {
        groups: {
            in: {
                position: 'left',
                attrs: {
                    circle: {
                        r: 4,
                        magnet: true,
                        stroke: 'transparent',
                        strokeWidth: 1,
                        fill: 'transparent',
                    },
                },
            },

            out: {
                position: {
                    name: 'right',
                    args: {
                        dx: -32,
                    },
                },

                attrs: {
                    circle: {
                        r: 4,
                        magnet: true,
                        stroke: 'transparent',
                        strokeWidth: 1,
                        fill: 'transparent',
                    },
                },
            },
        },
    },
})

// 注册连线
Graph.registerConnector(
    'curveConnector',
    (sourcePoint, targetPoint) => {
        const hgap = Math.abs(targetPoint.x - sourcePoint.x)
        const path = new Path()
        path.appendSegment(
            Path.createSegment('M', sourcePoint.x - 4, sourcePoint.y),
        )
        path.appendSegment(
            Path.createSegment('L', sourcePoint.x + 12, sourcePoint.y),
        )
        // 水平三阶贝塞尔曲线
        path.appendSegment(
            Path.createSegment(
                'C',
                sourcePoint.x < targetPoint.x
                    ? sourcePoint.x + hgap / 2
                    : sourcePoint.x - hgap / 2,
                sourcePoint.y,
                sourcePoint.x < targetPoint.x
                    ? targetPoint.x - hgap / 2
                    : targetPoint.x + hgap / 2,
                targetPoint.y,
                targetPoint.x - 6,
                targetPoint.y,
            ),
        )
        path.appendSegment(
            Path.createSegment('L', targetPoint.x + 2, targetPoint.y),
        )

        return path.serialize()
    },
    true,
)

Edge.config({
    markup: [
        {
            tagName: 'path',
            selector: 'wrap',
            attrs: {
                fill: 'none',
                cursor: 'pointer',
                stroke: 'transparent',
                strokeLinecap: 'round',
            },
        },
        {
            tagName: 'path',
            selector: 'line',
            attrs: {
                fill: 'none',
                pointerEvents: 'none',
            },
        },
    ],
    connector: { name: 'curveConnector' },
    attrs: {
        wrap: {
            connection: true,
            strokeWidth: 10,
            strokeLinejoin: 'round',
        },
        line: {
            connection: true,
            stroke: '#A2B1C3',
            strokeWidth: 1,
            targetMarker: {
                name: 'classic',
                size: 6,
            },
        },
    },
})

Graph.registerEdge('data-processing-curve', Edge, true)

// 节点状态列表
const nodeStatusList = [
    {
        id: 'node-start',
        status: 'success',
    },
]

// 边状态列表
const edgeStatusList = [
    {
        id: 'edge-0',
        status: 'success',
    },
]

// 显示节点状态
const showNodeStatus = () => {
    nodeStatusList.forEach((item) => {
        const { id, status } = item
        const node = graph.value?.getCellById(id)
        const data = node?.getData() as CellStatus
        node?.setData({
            ...data,
            status,
        })
    })
}

// 开启边的运行动画
const excuteAnimate = () => {
    graph.value?.getEdges().forEach((edge) => {
        edge.attr({
            line: {
                stroke: '#3471F9',
            },
        })
        edge.attr('line/strokeDasharray', 5)
        edge.attr('line/style/animation', 'running-line 30s infinite linear')
    })
}

// 关闭边的动画
const stopAnimate = () => {
    graph.value?.getEdges().forEach((edge) => {
        edge.attr('line/strokeDasharray', 0)
        edge.attr('line/style/animation', '')
    })
    edgeStatusList.forEach((item) => {
        const { id, status } = item
        const edge = graph.value?.getCellById(id)
        console.log('edge', edge);
        if (status === 'success' && edge !== null) {
            edge?.attr('line/stroke', '#52c41a')
        }
        if (status === 'error' && edge !== null) {
            edge?.attr('line/stroke', '#ff4d4f')
        }
    })
    // 默认选中一个节点
    graph.value?.select('node-start')
}

const data = props.flowData !== '' ? JSON.parse(props.flowData) : {
    nodes: [
        {
            id: "node-start",
            shape: "data-processing-dag-node",
            x: 0,
            y: 100,
            ports: [
                {
                    id: "node-start-out",
                    group: "out"
                }
            ],
            data: {
                name: "开始",
                type: "START",
                checkStatus: "sucess"
            }
        },
    ],
    edges: []
}
const getGraphData = () => {
    return graph.value?.toJSON();
}
defineExpose({
    getGraphData
})
onMounted(() => {
    graph.value = new Graph({
        container: graphContainer.value,
        panning: {
            enabled: true,
            eventTypes: ['leftMouseDown', 'mouseWheel'],
        },
        grid: {
            visible: true,
            type: 'doubleMesh',
            args: [
                {
                    color: '#eee', // 主网格线颜色
                    thickness: 1, // 主网格线宽度
                },
                {
                    color: '#ddd', // 次网格线颜色
                    thickness: 1, // 次网格线宽度
                    factor: 4, // 主次网格线间隔
                },
            ],
        },
        mousewheel: {
            enabled: true,
            modifiers: 'ctrl',
            factor: 1.1,
            maxScale: 1.5,
            minScale: 0.5,
        },
        highlighting: {
            magnetAdsorbed: {
                name: 'stroke',
                args: {
                    attrs: {
                        fill: '#fff',
                        stroke: '#31d0c6',
                        strokeWidth: 4,
                    },
                },
            },
        },
        connecting: {
            snap: true,
            allowBlank: false,
            allowLoop: false,
            highlight: true,
            sourceAnchor: {
                name: 'left',
                args: {
                    dx: Platform.IS_SAFARI ? 4 : 8,
                },
            },
            targetAnchor: {
                name: 'right',
                args: {
                    dx: Platform.IS_SAFARI ? 4 : -8,
                },
            },
            createEdge() {
                return graph.value?.createEdge({
                    shape: 'data-processing-curve',
                    attrs: {
                        line: {
                            strokeDasharray: '5 5',
                        },
                    },
                    zIndex: -1,
                })
            },
            // 连接桩校验
            validateConnection({ sourceMagnet, targetMagnet }) {
                // 只能从输出链接桩创建连接
                if (!sourceMagnet || sourceMagnet.getAttribute('port-group') === 'in') {
                    return false
                }
                // 只能连接到输入链接桩
                if (!targetMagnet || targetMagnet.getAttribute('port-group') !== 'in') {
                    return false
                }
                return true
            },
        },
    })

    graph.value?.use(
        new Selection({
            multiple: true,
            rubberEdge: true,
            rubberNode: true,
            modifiers: 'shift',
            rubberband: true,
        }),
    )

    graph.value?.fromJSON(data)
    const zoomOptions = {
        padding: {
            left: 10,
            right: 10,
        },
    }
    graph.value?.zoomToFit(zoomOptions)
    setTimeout(() => {
        excuteAnimate()
    }, 2000)
    setTimeout(() => {
        showNodeStatus()
        stopAnimate()
    }, 1000)
})

</script>
<style scoped>
.backgournd-grid-app {
    display: flex;
    width: 100%;
    padding: 0;
    font-family: sans-serif;
}

.app-content {
    flex: 1;
    height: 65vh;
    margin-right: 8px;
    margin-left: 8px;
    border-radius: 5px;
    box-shadow: 0 12px 5px -10px rgb(0 0 0 / 10%), 0 0 4px 0 rgb(0 0 0 / 10%);
}
</style>